package edu.gatech.cs2340.teamrocket.control.guicontrol;

import edu.gatech.cs2340.teamrocket.control.exception.ItemHasNoEffectException;
import edu.gatech.cs2340.teamrocket.control.networking.impl.VTNetworkingInterface;
import java.util.List;
import java.util.Observable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Observer;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import edu.gatech.cs2340.teamrocket.control.turnlogic.DefaultTurnLogic;
import edu.gatech.cs2340.teamrocket.model.Model;
import edu.gatech.cs2340.teamrocket.model.environment.Weather;
import edu.gatech.cs2340.teamrocket.model.item.Item;
import edu.gatech.cs2340.teamrocket.model.map.Location;
import edu.gatech.cs2340.teamrocket.model.pokemon.Pokemon;
import edu.gatech.cs2340.teamrocket.view.*;
import edu.gatech.cs2340.teamrocket.view.main.*;
import edu.gatech.cs2340.teamrocket.view.networking.ChatDisplay;

/**
 *
 * @author Wai Chip Ngai
 * This is the controller for the main game panel
 *
 */
public class MainGamePanelControl implements Observer, ActionListener{

	private static final String OPTION_MAIN_MENU = "Main Menu";
	private static final String OPTION_SAVE = "Save";
	private static final String OPTION_LOAD = "Load";
	private static final String OPTION_RESTART = "Restart";
	private static final String OPTION_CANCEL = "Cancel";
	private static String[] MENU_OPTIONS = {
		OPTION_CANCEL,
		OPTION_MAIN_MENU,
		OPTION_RESTART,
		OPTION_LOAD,
		OPTION_SAVE
	};

	private JPanel bottomPanel, centerPanel, mainGamePanel, rightPanel, topPanel, inventoryPanel, wagonPanel, chatPanel;
	private JTabbedPane leftPanel;
	private JLabel inventoryLabel, wagonLabel, locationLabel, environmentLabel;
	private GameFrame gf;
	private Model model;
	private List<Location> allLocations;
	private MapFrame mapFrame;
	private JButton potion, fullHeal;
	private String[] pokemonList;
	private JComboBox pokemonSelect;

	/**
	 * It creates the 5 panels that make up the main game panel and put them together
	 * @param gf the main Game Frame
	 */
	public MainGamePanelControl(GameFrame gf){

		this.gf = gf;
		model = Model.getInstance();
		model.addObserver(this);
		allLocations = model.getAllLocations();
		if(model.hasLocalShop())
			new ShopControl(gf, this, model.getLocalShop());

		mainGamePanel = new MainGamePanel();
		gf.add(mainGamePanel,GameFrame.MAIN_GAME_JAPNEL);

		pokemonList = new String[model.getPokemon().size()];
		int index = 0;
		for (Pokemon p : model.getPokemon()){
			pokemonList[index] = p.getName();
			index++;
		}
		pokemonSelect = new JComboBox(pokemonList);
		bottomPanel = new BottomPanel(this);
		centerPanel = new CenterPanel();
		leftPanel = new LeftPanel();
		rightPanel = new RightPanel();
		topPanel = new TopPanel();

		mainGamePanel.add(topPanel, BorderLayout.NORTH);
		mainGamePanel.add(bottomPanel, BorderLayout.SOUTH);
		mainGamePanel.add(leftPanel, BorderLayout.WEST);
		mainGamePanel.add(rightPanel, BorderLayout.EAST);
		mainGamePanel.add(centerPanel, BorderLayout.CENTER);

		setUpWagonPanel();
		setUpInventoryPanel();
		refreshVisualPanel();

		VTNetworkingInterface net = VTNetworkingInterface.getInstance();
		if(net.clientIsRunning()){
			setUpChatPanel();
			net.setChatDisplay((ChatDisplay)chatPanel);
		}
	}

	/**
	 * Add items to the top JPanel
	 */
	//private void addTopPanelLabels(){
		//topPanel.add(new JLabel("YO, What's up, "+wagon.getPokemon().get(0).getTrainerName()+" and your fellow teammates!!",JLabel.CENTER));
	//}

	/**
	 * What happens when the menu button is pressed in the game
	 */
	public void menu(){
		int choice = JOptionPane.showOptionDialog(
				null,
				"What do you want to do?",
				"Menu",
				JOptionPane.DEFAULT_OPTION,
				JOptionPane.QUESTION_MESSAGE,
				null,
				MENU_OPTIONS,
				OPTION_CANCEL
				);
		if(choice < 0)
			return; // player hit corner close button
		if(MENU_OPTIONS[choice].equals(OPTION_MAIN_MENU)){
			// go the main menu
			Model.resetInstance();
			new MainMenuControl(gf);
		}
		else if(MENU_OPTIONS[choice].equals(OPTION_SAVE)){
			try{
				model.saveGameData();
				JOptionPane.showMessageDialog(null, "The game was successfully saved.");
			}
			catch(IOException e){
				JOptionPane.showMessageDialog(null, "There was a problem saving the game. The game was not saved.");
				e.printStackTrace();
			}
		}
		else if(MENU_OPTIONS[choice].equals(OPTION_LOAD)){
			try{
				model.loadGameData();
				((TopPanel)topPanel).setLabel(model.getUpdates());
				JOptionPane.showMessageDialog(null, "The game was successfully loaded.");
				gf.showPanel(GameFrame.MAIN_GAME_JAPNEL);
			}
			catch(FileNotFoundException e){
				JOptionPane.showMessageDialog(null, "There are no saved games to load.");
			}
			catch(IOException e){
				JOptionPane.showMessageDialog(null, "There was a problem loading the game. The game was not loaded.");
			}
		}
		else if(MENU_OPTIONS[choice].equals(OPTION_RESTART)){
			// go the game intro gui
			restartGame();
		}
		else if(MENU_OPTIONS[choice].equals(OPTION_CANCEL)){
			// do nothing
		}
		else{
			throw new RuntimeException("Inavlid menu selection");
		}
	}

	/**
	 * A method restarting the game
	 */
	public void restartGame(){
		Model.resetInstance();
		new IntroScreenControl(gf);
	}

	/**
	 * What happens when the stats button is pressed in the game
	 */
	public void stats(){
		JOptionPane.showMessageDialog(null, model.statsToHTML());
	}

	/**
	 * Create a tap under the left panel to display inventory information
	 */
	private void setUpInventoryPanel(){
		inventoryPanel = new JPanel();
		leftPanel.add("Inventory", inventoryPanel);
		inventoryPanel.setBorder(BorderFactory.createTitledBorder(
				BorderFactory.createEtchedBorder(), "Your Backpack: "));
		//inventoryPanel.setLayout(new GridLayout(6,1));

		inventoryLabel = new JLabel(model.backpackToHTML());

		potion = new JButton("Use Potion");
		fullHeal = new JButton("Use FullHeal");
		potion.addActionListener(this);
		fullHeal.addActionListener(this);
		inventoryLabel.setPreferredSize(new Dimension(170,150));
		potion.setPreferredSize(new Dimension(170,50));
		fullHeal.setPreferredSize(new Dimension(170,50));
		pokemonSelect.setPreferredSize(new Dimension(170,50));

		inventoryPanel.add(inventoryLabel);
		inventoryPanel.add(new JLabel(""));
		inventoryPanel.add(potion);
		inventoryPanel.add(fullHeal);
		inventoryPanel.add(pokemonSelect);
	}

	/**
	 * Create a tap under the left panel to display basic information for the team members
	 */
	private void setUpWagonPanel(){
		wagonPanel = new JPanel();
		leftPanel.add("Info", wagonPanel);
		wagonPanel.setBorder(BorderFactory.createTitledBorder(
				BorderFactory.createEtchedBorder(), "Basic Info: "));
		//wagonPanel.setLayout(new GridLayout(3,1));

		wagonLabel = new JLabel(model.wagonToHTML());
		locationLabel = new JLabel(model.mapToHTML());
		environmentLabel = new JLabel(model.environmentToHTML());
		wagonLabel.setPreferredSize(new Dimension(170,250));
		locationLabel.setPreferredSize(new Dimension(170,50));
		environmentLabel.setPreferredSize(new Dimension(170,150));

		wagonPanel.add(wagonLabel);
		wagonPanel.add(locationLabel);
		wagonPanel.add(environmentLabel);

	}

	private void setUpChatPanel(){
		chatPanel = new ChatPanel();
		leftPanel.add("Chat", chatPanel);
	}

	/**
	 * refresh the main panel that displays weather and terrain conditions
	 * as an image.  Currently only displays weather.
	 * @author Margaret Markey
	 */
	private void refreshVisualPanel() {
		Weather w = model.getWeather();
		((CenterPanel) centerPanel).updatePicture(w);
	}

	/**
	 * show the shop panel when the user chooses to visit shop
	 */
	public void shop(){
		gf.showPanel( GameFrame.SHOP_GUI_JPANEL);
	}

	/**
	 * What happens when the player wants to view the map
	 */
	public void map(){
		if (mapFrame != null){
			mapFrame.setVisible(false);
		}
		mapFrame = new MapFrame(new VisualMap(allLocations, model));
	}

	/**
	 * What happens when the user chooses to end the turn
	 */
	public void nextTurn(){
		model.setTeamRations(((RightPanel) rightPanel).getSelectedRations());
		model.setTeamSpeed(((RightPanel) rightPanel).getSelectedSpeed());
		List<String> updates = new DefaultTurnLogic().nextTurn();
		for(String aString: updates){
			((TopPanel) topPanel).updateLabel(aString);
		}
		((TopPanel) topPanel).updateLabel("You have traveled "+model.getDistanceTraveled()+" Kilometer");
		refreshInventoryPanel();
		refreshVisualPanel();
		refreshWagonPanel();
		if (model.hasLocalShop()){
			((BottomPanel) bottomPanel).setShop(true);
			new ShopControl(gf, this, model.getLocalShop());
		}
		else{
			((BottomPanel) bottomPanel).setShop(false);
		}
		if(model.isAtEndOfMap()){
			JOptionPane.showMessageDialog(null, "Congrats! You bet the Victory Trail!");
			((BottomPanel) bottomPanel).endGame();
		}
		if(model.teamIsFainted()){
			JOptionPane.showMessageDialog(null, "You are out of usable Pokemon! You whited out! (Game Over)");
			((BottomPanel) bottomPanel).endGame();
		}
		((RightPanel)rightPanel).setSelectedSpeed(model.getTeamSpeed());
	}

	/**
	 * updates text on the Inventory Panel
	 */
	public void refreshInventoryPanel(){
		inventoryLabel.setText(model.backpackToHTML());
	}

	/**
	 * updates text on the Inventory Panel
	 */
	public void refreshWagonPanel(){
		wagonLabel.setText(model.wagonToHTML());
		locationLabel.setText(model.mapToHTML());
		environmentLabel.setText(model.environmentToHTML());
	}

	@Override
	public void update(Observable o, Object o1) {
		refreshInventoryPanel();
		refreshWagonPanel();
	}

	public void setUpdatesLabel(List<String> list){
		((TopPanel)topPanel).setLabel(list);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource().equals(potion)){
			Pokemon aPokemon = model.getPokemon().get(pokemonSelect.getSelectedIndex());
			try {
				if (model.getBackpack().canSellItem(Item.Potion)){
					aPokemon.heal(100);
					model.getBackpack().removeItem(Item.Potion);
					String aString = aPokemon.getName()+" used a potion";
					((TopPanel) topPanel).updateLabel(aString);
					refreshInventoryPanel();
					refreshWagonPanel();
					
				}else{
					JOptionPane.showMessageDialog(null, "You ain't got no Potions");
				}
			} catch (ItemHasNoEffectException e1) {
				JOptionPane.showMessageDialog(null, e1.getMessage());
			}
		}else if(e.getSource().equals(fullHeal)){
			Pokemon aPokemon = model.getPokemon().get(pokemonSelect.getSelectedIndex());
			try {
				if (model.getBackpack().canSellItem(Item.FullHeal)){
					aPokemon.healAilment();
					model.getBackpack().removeItem(Item.FullHeal);
					String aString = aPokemon.getName()+" used a FullHeal";
					((TopPanel) topPanel).updateLabel(aString);
					refreshInventoryPanel();
					refreshWagonPanel();
				}else{
					JOptionPane.showMessageDialog(null, "You ain't got no Full Heal");
				}
			} catch (ItemHasNoEffectException e1) {
				JOptionPane.showMessageDialog(null, e1.getMessage());
			}
		}

	}
}
